#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>	
#include <unistd.h>
#include <signal.h>
#include "sys_timer.h"

pthread_t pThreadTmrMgrId = 0;

struct itimerval TimerVal;

const long	dwDiv = 1000;
static long g_dwTimeTickCout; 
/*Mutex lock.*/
static pthread_mutex_t TmrMutexVal = PTHREAD_MUTEX_INITIALIZER;
/*Tick lock.*/
static pthread_mutex_t Ticklock = PTHREAD_MUTEX_INITIALIZER;

unsigned short g_dwSysOldTicks;	
unsigned short g_dwSysCurTicks;	

TSYS_TIMER_MA  g_tSysTimerTable; 
TSYS_TIMER_NODE  g_atSysTimerNode[SYS_MAX_TIMER_NUM];

int sys_timer_init(void)
{
       int byI = 0;		
		
       g_dwSysOldTicks = 0;		
       pthread_mutex_lock(&TmrMutexVal);

	memset(g_atSysTimerNode, 0, sizeof(g_atSysTimerNode));
       for (byI = 0; byI < SYS_MAX_TIMER_NUM; byI++) {
       	g_atSysTimerNode[byI].timer_id = byI;
              if ((SYS_MAX_TIMER_NUM - 1) == byI) {
                     g_atSysTimerNode[byI].ptNext = NULL;
              }
              else{
              	g_atSysTimerNode[byI].ptNext = (TSYS_TIMER_NODE *)&g_atSysTimerNode[byI + 1];
              }
       }
        g_tSysTimerTable.byIdleNum = SYS_MAX_TIMER_NUM;
        g_tSysTimerTable.byUseNum = 0;
        g_tSysTimerTable.ptTimerIdle = (TSYS_TIMER_NODE *)g_atSysTimerNode;
        g_tSysTimerTable.ptTimerUse = NULL;

        pthread_mutex_unlock(&TmrMutexVal);
        return (0);
}

int sys_timer_create(int module_id, ETIMER_TYPE timer_type)
{
        TSYS_TIMER_NODE  *ptTimer = NULL;

        if (module_id >= ESYS_MODULE_MAX)
        {
                return (ETIMER_PROC_ERR);
        }

        if (0 == g_tSysTimerTable.byIdleNum)
        {
                return (ETIMER_PROC_ERR);
        }
        pthread_mutex_lock(&TmrMutexVal);
        ptTimer = g_tSysTimerTable.ptTimerIdle;

        g_tSysTimerTable.byIdleNum--;
        if (0 == g_tSysTimerTable.byIdleNum)
        {
                g_tSysTimerTable.ptTimerIdle = NULL;
        }
        else
        {
                g_tSysTimerTable.ptTimerIdle = ptTimer->ptNext;
        }
        g_tSysTimerTable.byUseNum++;
        if (NULL == g_tSysTimerTable.ptTimerUse)
        {
                ptTimer->ptPre = NULL;
                ptTimer->ptNext = NULL;
        }
        else
        {
                ptTimer->ptPre = NULL;
                ptTimer->ptNext = g_tSysTimerTable.ptTimerUse;
                g_tSysTimerTable.ptTimerUse->ptPre = ptTimer;
        }
        g_tSysTimerTable.ptTimerUse = ptTimer;
        pthread_mutex_unlock(&TmrMutexVal);
        ptTimer->module_id = module_id;
        ptTimer->timer_type = timer_type;
        ptTimer->eState = ETIMER_STOP;
        ptTimer->wTickOffset = 0;
        ptTimer->dwTimerLimit = 0;
        ptTimer->pvTimeFunc = NULL;
        ptTimer->argc = 0;
        ptTimer->argv = NULL;
        return (ptTimer->timer_id);

}

int sys_timer_delete(int timer_id)
{
        TSYS_TIMER_NODE  *ptTimer = NULL;	
        TSYS_TIMER_NODE  *ptTimerPre = NULL;
        TSYS_TIMER_NODE  *ptTimerNext = NULL;	

        if (timer_id >= SYS_MAX_TIMER_NUM){
                return (ETIMER_PARA_ERR);
        }
        if (ETIMER_IDLE == g_atSysTimerNode[timer_id].eState){
                return (ETIMER_NO_EXIST);
        }

        if (0 == g_tSysTimerTable.byUseNum){
                return (ETIMER_NO_EXIST);
        }

        ptTimer = (TSYS_TIMER_NODE *)&g_atSysTimerNode[timer_id];
        pthread_mutex_lock(&TmrMutexVal);
        g_tSysTimerTable.byUseNum--;

        if (0 == g_tSysTimerTable.byUseNum){
                g_tSysTimerTable.ptTimerUse = NULL;
        }
        else{
                ptTimerPre = ptTimer->ptPre;		
                ptTimerNext= ptTimer->ptNext;	

                if ((NULL != ptTimerPre) && (NULL != ptTimerNext)){
                        ptTimerPre->ptNext = ptTimerNext;
                        ptTimerNext->ptPre = ptTimerPre;
                }
                else if (NULL == ptTimerPre){
                        ptTimerNext->ptPre = NULL;
                        g_tSysTimerTable.ptTimerUse = ptTimerNext;
                }
                else if (NULL == ptTimerNext){
                        ptTimerPre->ptNext = NULL;
                }
                else{
                        return (ETIMER_PROC_ERR);
                }
        }
        memset(&g_atSysTimerNode[timer_id], 0, sizeof(TSYS_TIMER_NODE));
        g_atSysTimerNode[timer_id].timer_id = timer_id;		
        if (NULL == g_tSysTimerTable.ptTimerIdle){
                g_tSysTimerTable.ptTimerIdle = ptTimer;
        }
        else{
                ptTimer->ptNext = g_tSysTimerTable.ptTimerIdle;
                g_tSysTimerTable.ptTimerIdle = ptTimer;
        }
        g_tSysTimerTable.byIdleNum++;
        pthread_mutex_unlock(&TmrMutexVal);
        return (ETIMER_OK);
}

//Timer_delay: (ms)
int sys_timer_start(int timer_id, int timer_delay, void *timer_func,int argc,char ** argv)
{
        int  wTickOffset = 0;		
        unsigned int g_dwSysCurTicksTmp=0;
   
        if (timer_id >= SYS_MAX_TIMER_NUM){
                return (ETIMER_PARA_ERR);
        }

        if (NULL == timer_func){
                return (ETIMER_PARA_ERR);
        }

        if (ETIMER_IDLE == g_atSysTimerNode[timer_id].eState){
                return (ETIMER_NO_EXIST);
        }

        wTickOffset = timer_delay/200;
        //wTickOffset = wTickOffset/SYS_TICK_MULTIPLE
        pthread_mutex_lock(&Ticklock);
        g_dwSysCurTicksTmp=g_dwSysCurTicks;
        pthread_mutex_unlock(&Ticklock);
        pthread_mutex_lock(&TmrMutexVal);
        g_atSysTimerNode[timer_id].eState = ETIMER_START;
        g_atSysTimerNode[timer_id].wTickOffset = wTickOffset;
        g_atSysTimerNode[timer_id].dwTimerLimit = g_dwSysCurTicksTmp + wTickOffset;
        g_atSysTimerNode[timer_id].pvTimeFunc = timer_func;
        g_atSysTimerNode[timer_id].argc = argc;
        g_atSysTimerNode[timer_id].argv = argv;
        pthread_mutex_unlock(&TmrMutexVal);
        return (ETIMER_OK);
}
int sys_timer_stop(int timer_id)
{
        if (timer_id >= SYS_MAX_TIMER_NUM){
                return (ETIMER_PARA_ERR);
        }
        if (ETIMER_IDLE == g_atSysTimerNode[timer_id].eState){
                return (ETIMER_NO_EXIST);
        }
        pthread_mutex_lock(&TmrMutexVal);
        g_atSysTimerNode[timer_id].eState = ETIMER_STOP;
        pthread_mutex_unlock(&TmrMutexVal);
        return (ETIMER_OK);
}

static void sys_sighandler(long timer_sig)
{
	TSYS_TIMER_NODE  *ptTimer = NULL;	
    	g_dwTimeTickCout++;

       g_dwTimeTickCout = 0 ;

       pthread_mutex_lock(&Ticklock);
       g_dwSysCurTicks++;
       g_dwSysOldTicks=g_dwSysCurTicks;
       pthread_mutex_unlock(&Ticklock);
       pthread_mutex_lock(&TmrMutexVal);
       ptTimer = g_tSysTimerTable.ptTimerUse;	
       while (ptTimer != NULL){
       	if (ETIMER_START == ptTimer->eState){
              	if (g_dwSysOldTicks >= ptTimer->dwTimerLimit) {
                     	ptTimer->pvTimeFunc(ptTimer->argc,ptTimer->argv);
                            if (ETIMER_ONE == ptTimer->timer_type){
                            	ptTimer->eState = ETIMER_STOP;
                            }
				else{
                            	ptTimer->dwTimerLimit = g_dwSysOldTicks + ptTimer->wTickOffset;
                            }
                     }
              }
              ptTimer = ptTimer->ptNext;
        }
        pthread_mutex_unlock(&TmrMutexVal);
}

int sys_timer_getstate(int timer_id)
{
	return g_atSysTimerNode[timer_id].eState;
}
int sys_timer_callback_func(int argc,char** argv)
{
	return 0;
}

void sys_timer_msleep(int time_msec)
{
	int timer_id;
	timer_id=sys_timer_create(1,ETIMER_ONE);
	sys_timer_start(timer_id,time_msec,sys_timer_callback_func,0,NULL);
	while(1)
	{
		if(ETIMER_STOP==sys_timer_getstate(timer_id))
			{
				sys_timer_delete(timer_id);
				return;
			}
			usleep(1000);
	}
}

void sys_timer_proc(void *pv_para)
{
	pv_para = pv_para;		/*avoid warnning*/
	
       signal(SIGALRM, (void *)sys_sighandler);
	TimerVal.it_interval.tv_sec = 0;/**/
       TimerVal.it_interval.tv_usec = dwDiv*200;
       TimerVal.it_value.tv_sec = 0;
       TimerVal.it_value.tv_usec = dwDiv*200;
       setitimer(ITIMER_REAL, &TimerVal, NULL);

	printf("create the timer proc!!!!!\n");
       for(;;)
       {
       	//wait for kernel 
       	sleep(1000);
       }
}
void say_hello(void)
{
	printf("Hello the crule world\n");
}
int main(void)
{
	int module = 10;
	int timer_id = 0;
	
	//init timer structure
	sys_timer_init();

	//create a timer
	timer_id = sys_timer_create(module, ETIMER_LOOP);
	if(ETIMER_PROC_ERR == timer_id){
		printf("Can not create timer\n");
	}
	sys_timer_start(timer_id, 1000, &say_hello,0, NULL);
	while(1){
		sys_timer_proc(NULL);
	}
	
	sys_timer_stop(timer_id);
	sys_timer_delete(timer_id);
	
	return 0;
}

